package com.zb.code.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zb.code.service.ConCodeService;
import com.zb.constant.CodeConstant;
import com.zb.excel.converter.CodeConverter;
import com.zb.entity.*;
import com.zb.entity.CodeUserRegisterVo;
import com.zb.extend.CodeExtend;
import com.zb.extend.CodeLogExtend;
import com.zb.result.PageUtil;
import com.zb.service.*;
import com.zb.view.ViewGoods;
import com.zb.vo.*;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * @Author WEN
 * @Date 2023/8/23 0023
 **/
@Service
public class ConCodeServiceImpl implements ConCodeService {
    @Resource
    private ZjCodeSetService setService;
    @Resource
    private ZjCodeBatchService batchService;
    @Resource
    private ZjCodeBatchGoodsService codeBatchGoodsService;
    @Resource
    private ZjProductService productService;
    @Resource
    private ZjSpareService spareService;
    @Resource
    private ZjCodeService codeService;
    @Resource(name = "asyncServiceExecutor")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Resource
    private ZjCodeInfoService codeInfoService;
    @Resource
    private ZjWorkGoodsCodeService workGoodsCodeService;
    @Resource
    private ZjWorkOrderService workOrderService;
    @Resource
    private ZjWorkUserService workUserService;
    @Resource
    private ZjWorkLevelService workLevelService;
    @Resource
    private ViewGoodsService viewGoodsService;
    @Resource
    private ZjNetworkService networkService;
    @Resource
    private ZjCodeBatchService codeBatchService;
    @Resource
    private ZjCodeUserRegisterService codeUserRegisterService;
    @Resource
    private ZjStoreService storeService;
    @Resource
    private ZjStorePositionService storePositionService;
    @Resource
    private ZjStoreInboundMaterialCodeService storeInboundMaterialCodeService;
    @Resource
    private ZjStoreOutboundMaterialCodeService storeOutboundMaterialCodeService;

    // 新增编码
    @Override
    @Transactional
    public void save(AccounLoginInfo loginInfo, CodeBatchVo codeBatchVo, CodeParamInfo codeParamInfo) {
        Integer total = 0;
        for (CodeVo codeVo : codeBatchVo.getCodeVos()) {
            Assert.isTrue(codeVo.getQty() <= 50000, "编码数量必须为 >0 的正整数，且单个编码数量 <= 50000");
            total += codeVo.getQty();
        }
        Assert.isTrue(total <= 300000, "编码数量必须为 >0 的正整数，且总编码数量 <=300,000");
        codeBatchVo.setQty(total);
        List<GoodsInfo> goodsInfos = null;
        if (Objects.equals(1, codeBatchVo.getType())) {
            goodsInfos = productService.getInfoByIds(codeBatchVo.getCodeVos().stream().map(CodeVo::getGoodsId).toList());
        }
        if (Objects.equals(2, codeBatchVo.getType())) {
            goodsInfos = spareService.getInfoByIds(codeBatchVo.getCodeVos().stream().map(CodeVo::getGoodsId).toList());
        }
        Assert.isTrue(null != goodsInfos && !goodsInfos.isEmpty(), "商品数据不存在！");

        ZjCodeSet codeSet = setService.getById(loginInfo.getCustAccId());
        Long codeBathId = batchService.save(loginInfo, codeSet.getBatchPrefix(), codeBatchVo, codeParamInfo.getCodeSource());
        codeBatchGoodsService.save(loginInfo.getCustAccId(), codeBathId, codeBatchVo.getCodeVos());

        // 编码规则
        codeParamInfo.setCodeBatchId(codeBathId);
        codeParamInfo.setType(codeBatchVo.getType());
        codeParamInfo.setCodeRule(codeParamInfo.isTemporary()? codeSet.getTemporRule() : codeSet.getCodeRule());
        codeParamInfo.setCodePrefix(codeParamInfo.isTemporary()? codeSet.getTemporaryPrefix() : codeSet.getCodePrefix());
        codeParamInfo.setStorehouseRule(codeSet.getStorehouseRule());
        codeParamInfo.setStorehousePrefix(codeSet.getStorehousePrefix());
        for (CodeVo codeVo : codeBatchVo.getCodeVos()) {
            codeParamInfo.setDate(goodsInfos.stream().filter(vo -> Objects.equals(codeVo.getGoodsId(), vo.getId())).map(GoodsInfo::getDate).toList().get(0));
            threadPoolTaskExecutor.execute(() -> {
                codeService.save(loginInfo, codeVo, codeParamInfo);
            });
        }
    }

    // 查询编码列表详情
    @Override
    public CodeDetailVo getInfo(Long id) {
        CodeExtend code = codeService.getDetailById(id);
        CodeDetailVo detailVo = new CodeDetailVo();
        BeanUtils.copyProperties(code, detailVo);
        detailVo.setCodeDisableStatus(code.getDisabled());
        detailVo.setCreateTime(code.getGmtCreate());
        detailVo.setUpdateTime(code.getGmtUpdate());
        detailVo.setBatchCode(codeBatchService.getById(code.getBatchId()).getCode());

        if (null != code.getNetworkId() && code.getNetworkId() != 0) {
            detailVo.setNetwork(networkService.getNameById(code.getNetworkId()));
        }

        ZjCodeInfo info = codeInfoService.getInfoById(id);
        detailVo.setFirstSelectTime(info.getFirstSelectTime());
        detailVo.setLastSelectTime(info.getLastSelectTime());
        detailVo.setSelectNum(info.getSelectNum());
        detailVo.setInboundCode(info.getInboundCode());
        detailVo.setInboundTime(info.getInboundTime());
        detailVo.setOutboundCode(info.getOutboundCode());
        detailVo.setOutboundTime(info.getOutboundTime());
        ViewGoods viewGoods = viewGoodsService.getByGoodsTypeAndGoodsIdAndGoodsSpecId(code.getType(), code.getGoodsId(), code.getGoodsSpecId());
        if (null != viewGoods) {
            detailVo.setBrandId(viewGoods.getBrandId());
            detailVo.setBrand(viewGoods.getBrand());
            detailVo.setGoodsName(viewGoods.getName());
            detailVo.setModel(viewGoods.getModel());
            detailVo.setGoodsSpecName(viewGoods.getSpecName());
        }

        // 编码登记信息
        detailVo.setRegister(info.getRegister());
        detailVo.setRegisterTime(info.getRegisterTime());
        ZjCodeUserRegister register = codeUserRegisterService.getById(id);
        if (null != register) {
            detailVo.setUsername(register.getName());
            detailVo.setPhone(register.getPhone());
            detailVo.setProvince(register.getProvince());
            detailVo.setCity(register.getCity());
            detailVo.setArea(register.getArea());
            detailVo.setTown(register.getTown());
            detailVo.setAddress(register.getAddress());
        }
        return detailVo;
    }

    // 批量删除编码
    @Override
    @Transactional
    public void deleteBatchByIds(List<CodeParamVo> codeParamVos) {
        Assert.isTrue(null != codeParamVos || !codeParamVos.isEmpty(), "请传入要删除的编码信息");
        List<Long> codeIds = codeParamVos.stream().map(CodeParamVo::getId).toList();
        codeService.checkCodeRelationInfoByIds(codeIds);
        List<Long> workCodeIds = workGoodsCodeService.getRelationCodeIdByCodeIds(codeIds);
        List<String> codes = codeInfoService.getRegistCodeByIds(workCodeIds);
        Assert.isTrue(CollectionUtil.isEmpty(codes), "一物一码已与工单商品关联，不可删除["+ String.join("、", codes) +"]");
        // 编码入库
        codes = storeInboundMaterialCodeService.getCodeByDelCodeIds(codeIds);
        Assert.isTrue(CollectionUtil.isEmpty(codes), "一物一码已与入库商品关联，不可删除["+ String.join("、", codes) +"]");
        // 编码出库
        codes = storeOutboundMaterialCodeService.getCodeByDelCodeIds(codeIds);
        Assert.isTrue(CollectionUtil.isEmpty(codes), "一物一码已与出库商品关联，不可删除["+ String.join("、", codes) +"]");
        batchService.updateQtyByCodeIds(codeIds);
        codeService.deleteBatchByIds(codeParamVos);
    }

    // 创建产品编码
    @Override
    @Transactional
    public Map<String, List<Long>> saveProductTemporaryCode(AccounLoginInfo loginInfo, List<CodeVo> codeVos, OrderUserVo userVo) {
        if (null == codeVos || codeVos.isEmpty()) {
            return null;
        }
        CodeBatchVo codeBatchVo = new CodeBatchVo();
        codeBatchVo.setName("工单商品编码批次创建");
        codeBatchVo.setType(1);
        codeBatchVo.setCodeVos(codeVos);
        Integer qty = 0;
        for (CodeVo codeVo : codeVos) {
            qty += codeVo.getQty();
        }
        codeBatchVo.setQty(qty);

        CodeParamInfo codeParamInfo = new CodeParamInfo()
                .setCodeSource(CodeConstant.CODE_SOURCE_3)
                .setTemporary(true);

        ZjCodeSet codeSet = setService.getById(loginInfo.getCustAccId());
        Long codeBathId = batchService.save(loginInfo, codeSet.getBatchPrefix(), codeBatchVo, codeParamInfo.getCodeSource());
        codeBatchGoodsService.save(loginInfo.getCustAccId(), codeBathId, codeBatchVo.getCodeVos());

        codeParamInfo.setCodeBatchId(codeBathId)
                .setType(codeBatchVo.getType())
                .setCodeRule(codeSet.getTemporRule())
                .setCodePrefix(codeSet.getTemporaryPrefix())
                .setStorehouseRule(codeSet.getStorehouseRule())
                .setStorehousePrefix(codeSet.getStorehousePrefix())
                .setSyncCommitTransaction(false)
                .setCodeFromOrder(true);
        CodeUserRegisterVo codeUserRegister = new CodeUserRegisterVo();
        BeanUtils.copyProperties(userVo, codeUserRegister);
        codeParamInfo.setCodeUserRegister(codeUserRegister);

        List<GoodsInfo> goodsInfos = productService.getInfoByIds(codeBatchVo.getCodeVos().stream().map(CodeVo::getGoodsId).toList());
        Map<String, List<Long>> resultMap = new HashMap<>();
        for (CodeVo codeVo : codeVos) {
            codeParamInfo.setDate(goodsInfos.stream().filter(vo -> Objects.equals(codeVo.getGoodsId(), vo.getId())).map(GoodsInfo::getDate).findFirst().orElse(null));
            // 新增编码
            resultMap.put(codeVo.getGoodsId() + "_" + codeVo.getGoodsSpecId(), codeService.save(loginInfo, codeVo, codeParamInfo).stream().map(ZjCode::getId).toList());
        }
        return resultMap;
    }

    // 创建配件编码
    @Override
    public Map<String, List<ZjCode>> saveSpareTemporaryCode(AccounLoginInfo loginInfo, boolean outStore, String outInBoundNo, List<CodeVo> codeVos) {
        if (null == codeVos || codeVos.isEmpty()) {
            return null;
        }
        CodeBatchVo codeBatchVo = new CodeBatchVo();
        codeBatchVo.setName(outStore? "工单配件审核通过并出库创建" : "工单配件旧件入库并创建临时编码");
        codeBatchVo.setType(2);
        codeBatchVo.setCodeVos(codeVos);
        Integer qty = 0;
        for (CodeVo codeVo : codeVos) {
            qty += codeVo.getQty();
        }
        codeBatchVo.setQty(qty);
        ZjCodeSet codeSet = setService.getById(loginInfo.getCustAccId());
        CodeParamInfo codeParamInfo = new CodeParamInfo()
                .setCodeSource(CodeConstant.CODE_SOURCE_3)
                .setTemporary(true)
                .setType(codeBatchVo.getType())
                .setCodeRule(codeSet.getTemporRule())
                .setCodePrefix(codeSet.getTemporaryPrefix())
                .setStorehouseRule(codeSet.getStorehouseRule())
                .setStorehousePrefix(codeSet.getStorehousePrefix())
                .setSyncCommitTransaction(false)
                .setCodeFromOrder(true)
                .setOutStore(outStore)
                .setInStore(!outStore)
                .setOutInBoundNo(outInBoundNo);
        Long codeBathId = batchService.save(loginInfo, codeSet.getBatchPrefix(), codeBatchVo, codeParamInfo.getCodeSource());
        codeBatchGoodsService.save(loginInfo.getCustAccId(), codeBathId, codeBatchVo.getCodeVos());

        codeParamInfo.setCodeBatchId(codeBathId);
        List<GoodsInfo> goodsInfos = spareService.getInfoByIds(codeBatchVo.getCodeVos().stream().map(CodeVo::getGoodsId).toList());
        Map<String, List<ZjCode>> resultMap = new HashMap<>();
        for (CodeVo codeVo : codeVos) {
            codeParamInfo.setDate(goodsInfos.stream().filter(vo -> Objects.equals(codeVo.getGoodsId(), vo.getId())).map(GoodsInfo::getDate).toList().get(0));
            // 新增编码
            resultMap.put(codeVo.getGoodsId() + "_" + codeVo.getGoodsSpecId(), codeService.save(loginInfo, codeVo, codeParamInfo));
        }
        return resultMap;
    }

    // 编码登记
    @Override
    public void codeRegister(AccounLoginInfo loginInfo, List<OrderGoodsVo> orderGoodsVos, OrderUserVo userVo) {
        List<Long> codeIds = getCodeIds(orderGoodsVos);
        if (codeIds == null) return;
        // 根据编码ID查询是否重复登记
        List<String> registCode = codeInfoService.getRegistCodeByIds(codeIds);
        Assert.isTrue(registCode.isEmpty(), "编码["+ String.join("、", registCode) +"]已关联用户并登记，不可重复关联登记流程");
        List<ZjCode> codeList = checkCodeIdExist(codeIds);

        CodeDataVo codeDataVo = new CodeDataVo();
        ZjCode cde = null;
        List<OrderGoodsCodeVo> goodsCodes = null;
        for (OrderGoodsVo goodsVo : orderGoodsVos) {
            goodsCodes = new ArrayList<>();
            for (Long codeId : goodsVo.getCodeIds()) {
                cde = codeList.stream().filter(co -> Objects.equals(co.getId(), codeId)).findFirst().orElse(null);
                extractedNotRegisterCode(loginInfo, userVo, codeDataVo, cde, goodsVo, codeId);
                goodsCodes.add(new OrderGoodsCodeVo(codeId, cde.getSecurityCode()));
            }
            goodsVo.setGoodsCodes(goodsCodes);
        }
        codeService.saveCodeRegister(codeDataVo);
    }

    // 获取编码登记信息、并判断是否有未登记的
    @Override
    public void getCodeRegister(AccounLoginInfo loginInfo, List<OrderGoodsVo> orderGoodsVos, OrderUserVo userVo) {
        List<Long> codeIds = getCodeIds(orderGoodsVos);
        if (codeIds == null) return;
        List<ZjCode> codeList = checkCodeIdExist(codeIds);
        // 查询已登记的
        List<ZjCodeInfo> registerCode = codeInfoService.getRegistTimeByIds(codeIds);
        CodeDataVo codeDataVo = new CodeDataVo();
        ZjCode cde = null;
        List<OrderGoodsCodeVo> goodsCodes = null;
        for (OrderGoodsVo vo : orderGoodsVos) {
            goodsCodes = new ArrayList<>();
            for (Long codeId : vo.getCodeIds()) {
                cde = codeList.stream().filter(co -> Objects.equals(co.getId(), codeId)).findFirst().orElse(null);
                if (registerCode.stream().anyMatch(rgc -> Objects.equals(rgc.getId(), codeId))) {
                    if (null == vo.getBuyTime()) {
                        vo.setBuyTime(null == cde? null : cde.getWarrantyStartTime());
                    }
                    if (null == vo.getEndTime()) {
                        vo.setEndTime(null == cde? null : cde.getWarrantyEndTime());
                    }
                } else {
                    extractedNotRegisterCode(loginInfo, userVo, codeDataVo, cde, vo, codeId);
                }
                goodsCodes.add(new OrderGoodsCodeVo(codeId, cde.getSecurityCode()));
            }
            vo.setGoodsCodes(goodsCodes);
        }
        codeService.saveCodeRegister(codeDataVo);
    }

    private List<ZjCode> checkCodeIdExist(List<Long> codeIds) {
        List<ZjCode> codeList = codeService.getRegisterByIds(codeIds);
        StringBuffer buffer = new StringBuffer();
        codeIds.forEach(t -> {
            if (!codeList.stream().anyMatch(code -> Objects.equals(code.getId(), t))) {
                if (buffer.length() > 0) buffer.append("、");
                buffer.append(t);
            }
        });
        Assert.isTrue(buffer.isEmpty(), "编码ID参数["+ buffer.toString() + "]的数据不存在");
        return codeList;
    }

    private static List<Long> getCodeIds(List<OrderGoodsVo> orderGoodsVos) {
        if (null == orderGoodsVos || orderGoodsVos.isEmpty()) {
            return null;
        }
        List<Long> codeIds = new ArrayList<>();
        for (OrderGoodsVo vo : orderGoodsVos) {
            Assert.isTrue(vo.getQty() == 1, "已登记编码的商品数量不符合规定，已登记的编码商品数量只能是一个！");
            Assert.isTrue(null != vo.getCodeIds() && !vo.getCodeIds().isEmpty(), "已登记编码的商品编码ID参数不能为空");
            codeIds.addAll(vo.getCodeIds());
        }
        return codeIds;
    }

    /**
     * 封装未登记的编码数据
     * @param loginInfo
     * @param userVo
     * @param codeDataVo
     * @param cde
     * @param goodsVo
     * @param codeId
     */
    private static void extractedNotRegisterCode(AccounLoginInfo loginInfo, OrderUserVo userVo, CodeDataVo codeDataVo, ZjCode cde, OrderGoodsVo goodsVo, Long codeId) {
        ZjCodeLog log;
        ZjCodeUserRegister codeUserRegister;
        ZjCode code;
        ZjCodeInfo info;
        code = new ZjCode();
        code.setId(codeId);
        if (!cde.getActiva()) {
            code.setActiva(true);
            code.setActivaTime(new Date());
        }
        code.setOutStoreActiva(false);
        code.setOutStoreWarranty(false);
        code.setWarrantyStartTime(null == goodsVo.getBuyTime()? new Date() : goodsVo.getBuyTime());
        code.setWarrantyEndTime(DateUtils.addDays(code.getWarrantyStartTime(), cde.getWarrantyDay()));
        code.setStatus(new Date().after(code.getWarrantyEndTime())? CodeConstant.CODE_STATUS_3 : CodeConstant.CODE_STATUS_2);
        code.setStoreId(0L);
        code.setStorePositionId(0L);
        code.setStoreStatus(CodeConstant.STORE_STATUS_5);

        goodsVo.setBuyTime(code.getWarrantyStartTime());
        goodsVo.setEndTime(code.getWarrantyEndTime());

        info = new ZjCodeInfo();
        info.setId(code.getId());
        info.setRegister(true);
        info.setRegisterTime(new Date());

        codeUserRegister = new ZjCodeUserRegister();
        BeanUtils.copyProperties(userVo, codeUserRegister);
        codeUserRegister.setId(code.getId());
        codeUserRegister.setCustAccId(loginInfo.getCustAccId());

        log = new CodeLogExtend(loginInfo, CodeConstant.CODE_LOG_TYPE_1, code.getId(), "创建工单并关联且登记激活编码", "");

        codeDataVo.getRegisters().add(codeUserRegister);
        if (0 == CodeConstant.tableType(codeId)) {
            codeDataVo.getCodes().add(code);
            codeDataVo.getInfos().add(info);
            codeDataVo.getLogs().add(log);
            return;
        }
        if (1 == CodeConstant.tableType(codeId)) {
            codeDataVo.getCode02s().add(new ZjCode02(code));
            codeDataVo.getInfo02s().add(new ZjCodeInfo02(info));
            codeDataVo.getLog02s().add(new ZjCodeLog02(log));
            return;
        }
        if (2 == CodeConstant.tableType(codeId)) {
            codeDataVo.getCode03s().add(new ZjCode03(code));
            codeDataVo.getInfo03s().add(new ZjCodeInfo03(info));
            codeDataVo.getLog03s().add(new ZjCodeLog03(log));
            return;
        }
        if (3 == CodeConstant.tableType(codeId)) {
            codeDataVo.getCode04s().add(new ZjCode04(code));
            codeDataVo.getInfo04s().add(new ZjCodeInfo04(info));
            codeDataVo.getLog04s().add(new ZjCodeLog04(log));
            return;
        }
        if (4 == CodeConstant.tableType(codeId)) {
            codeDataVo.getCode05s().add(new ZjCode05(code));
            codeDataVo.getInfo05s().add(new ZjCodeInfo05(info));
            codeDataVo.getLog05s().add(new ZjCodeLog05(log));
        }
    }


    @Override
    public Map<String, Object> getHistoryOrder(Long codeId, PageUtil pageUtil) {
        PageUtil.setPageLimit(pageUtil);
        List<Long> workIds = workGoodsCodeService.getWorkIdsByCodeId(codeId);
        Page<ZjWorkOrder> page = workOrderService.PageGetHistoryOrder(workIds, pageUtil);
        List<Long> ids = page.getRecords().stream().map(ZjWorkOrder::getId).toList();
        List<Long> orderLevelIds = page.getRecords().stream().map(ZjWorkOrder::getWorkLevelId).distinct().toList();
        List<Long> networkIds = page.getRecords().stream().map(ZjWorkOrder::getNetworkId).distinct().toList();
        List<ZjWorkUser> workUsers = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(orderLevelIds)) {
            workUsers.addAll(workUserService.getByIds(ids));
        }
        List<ZjWorkLevel> workLevels = workLevelService.getByIds(orderLevelIds);
        List<ZjNetwork> networkList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(networkList))  {
            networkList.addAll(networkService.listByIds(networkIds));
        }
        List<CodeHistoryOrderVo> voList = page.getRecords().stream().map(order -> {
            CodeHistoryOrderVo vo = new CodeHistoryOrderVo();
            BeanUtils.copyProperties(order, vo);
            vo.setOrderNo(order.getCode());
            vo.setUpdateTime(order.getGmtUpdate());
            ZjWorkUser user = workUsers.stream().filter(workUser -> Objects.equals(workUser.getId(), order.getId())).findFirst().orElse(null);
            if (null != user) {
                vo.setUsername(user.getName());
                vo.setPhone(user.getPhone());
            }
            ZjWorkLevel workLevel = workLevels.stream().filter(level -> Objects.equals(level.getId(), order.getWorkLevelId())).findFirst().orElse(null);
            if (null != workLevel) {
                vo.setWorkLevel(workLevel.getName());
                vo.setWorkLevelColor(workLevel.getColor());
            }
            vo.setNetwork(networkList.stream().filter(f -> Objects.equals(f.getId(), order.getNetworkId())).map(ZjNetwork::getName).findFirst().orElse(""));
            return vo;
        }).toList();
        return PageUtil.pageList(page.getCurrent(), page.getSize(), page.getTotal(), voList);
    }

    // 获取未登记商品编码
    @Override
    public Map<String, Object> getNotRegisterCode(Long custAccId, OrderCodeSelectVo codeSelectVo) {
        PageUtil.setPageLimit(codeSelectVo);
        long count = codeService.getNotRegisterCodeCount(custAccId, codeSelectVo);
        if (count <= 0) {
            return PageUtil.pageList(codeSelectVo.getPage(), codeSelectVo.getLimit(), count, new ArrayList<>());
        }
        List<ZjCode> notRegisterCode = codeService.getNotRegisterCode(custAccId, codeSelectVo);
        List<Long> productIds = notRegisterCode.stream().map(ZjCode::getGoodsId).distinct().toList();
        List<Long> productSpecIds = notRegisterCode.stream().map(ZjCode::getGoodsSpecId).distinct().toList();
        List<ViewGoods> viewGoodsList = viewGoodsService.getByGoodsIdsAndGoodsSpecIds(productIds, productSpecIds);
        List<CodeNotRegisterVo> voList = notRegisterCode.stream().map(code -> {
            CodeNotRegisterVo vo = new CodeNotRegisterVo();
            BeanUtils.copyProperties(code, vo);
            vo.setCode(code.getSecurityCode());
            viewGoodsList.stream().filter(vi -> Objects.equals(1, vi.getGoodsType()) && Objects.equals(vi.getId(), code.getGoodsId()) && Objects.equals(vi.getSpecId(), code.getGoodsSpecId()))
                    .findFirst().ifPresent(specView -> {
                        vo.setGoodsBrand(specView.getBrand());
                        vo.setGoodsModel(specView.getModel());
                        vo.setGoodsName(specView.getName());
                        vo.setGoodsType(specView.getType());
                        vo.setGoodsSpecName(specView.getSpecName());
                    });
            return vo;
        }).toList();
        return PageUtil.pageList(codeSelectVo.getPage(), codeSelectVo.getLimit(), count, voList);
    }

    // 根据客户ID获取已登记编码
    @Override
    public Map<String, Object> getRegisterCode(Long custAccId, Long userId, OrderCodeSelectVo codeSelectVo) {
        if (null == userId || userId == 0) {
            return PageUtil.pageList(codeSelectVo.getPage(), codeSelectVo.getLimit(), 0L, new ArrayList<>());
        }
        PageUtil.setPageLimit(codeSelectVo);
        List<Long> goodsIds = null;
        if (null != codeSelectVo.getBrandId() || null != codeSelectVo.getTypeId() || StringUtils.isNotBlank(codeSelectVo.getModel())) {
            GoodsSelect goodsSelect = new GoodsSelect(custAccId, codeSelectVo.getBrandId(), codeSelectVo.getTypeId(), codeSelectVo.getModel());
            goodsSelect.setPage(codeSelectVo.getPage());
            goodsSelect.setLimit(codeSelectVo.getLimit());
            goodsIds = productService.pageGetIds(goodsSelect);
            if (goodsIds.isEmpty()) goodsIds.add(-1L);
        }
        List<CodeRegisterVo> voList = codeService.getRegisterCode(custAccId, userId, goodsIds, codeSelectVo);
        List<Long> productIds = voList.stream().map(CodeRegisterVo::getGoodsId).distinct().toList();
        List<Long> productSpecIds = voList.stream().map(CodeRegisterVo::getGoodsSpecId).distinct().toList();
        List<ViewGoods> viewGoodsList = viewGoodsService.getByGoodsIdsAndGoodsSpecIds(productIds, productSpecIds);
        voList.forEach(vo -> {
            vo.setStatus(CodeConverter.codeStatusConverter(vo.getStatus(), vo.getWarrantyEndTime()));
            vo.setOverInsured(null != vo.getWarrantyEndTime() && vo.getWarrantyEndTime().after(new Date()));
            viewGoodsList.stream().filter(vi -> Objects.equals(1, vi.getGoodsType()) && Objects.equals(vi.getId(), vo.getGoodsId()) && Objects.equals(vi.getSpecId(), vo.getGoodsSpecId()))
                    .findFirst().ifPresent(specView -> {
                vo.setGoodsBrand(specView.getBrand());
                vo.setGoodsModel(specView.getModel());
                vo.setGoodsName(specView.getName());
                vo.setGoodsType(specView.getType());
                vo.setGoodsSpecName(specView.getSpecName());
            });
        });
        return PageUtil.pageList(codeSelectVo.getPage(), codeSelectVo.getLimit(), codeService.getRegisterCodeCount(custAccId, userId, goodsIds, codeSelectVo), voList);
    }

    // 获取在库的一物一码
    @Override
    public Map<String, Object> getInStoreCodeList(Long custAccId, CodeInStoreListSearchVo searchVo) {
        PageUtil.setPageLimit(searchVo);
        List<ZjCode> codeList = codeService.getInStoreCodeList(custAccId, searchVo);

        List<Long> goodsIds = codeList.stream().map(ZjCode::getGoodsId).distinct().toList();
        List<Long> goodsSpecIds = codeList.stream().map(ZjCode::getGoodsSpecId).distinct().toList();
        List<ViewGoods> goodsList = viewGoodsService.getByGoodsIdsAndGoodsSpecIds(goodsIds, goodsSpecIds);

        List<Long> storePositionIds = codeList.stream().filter(f -> null != f.getStorePositionId() && f.getStorePositionId() > 0).map(ZjCode::getStoreId).distinct().toList();
        List<ZjStore> storeList = storeService.getStoreNameByIds(codeList.stream().filter(f -> null != f.getStoreId() && f.getStoreId() > 0).map(ZjCode::getStoreId).distinct().toList());
        List<ZjStorePosition> storePositions = storePositionService.getStorePositionNameByIds(storePositionIds);

        List<CodeInStoreListVo> voList = codeList.stream().map(code -> {
            CodeInStoreListVo vo = getStoreCodeData(goodsList, code);
            storeList.stream().filter(f -> Objects.equals(f.getId(), code.getStoreId())).findFirst().map(ZjStore::getName).ifPresent(vo::setStore);
            storePositions.stream().filter(f -> Objects.equals(f.getId(), code.getStoreId())).findFirst().map(ZjStorePosition::getName).ifPresent(vo::setStorePosition);
            return vo;
        }).toList();
        return PageUtil.pageList(searchVo.getPage(), searchVo.getLimit(), codeService.getInStoreCodeListCount(custAccId, searchVo), voList);
    }

    // 获取未出入库的一物一码
    @Override
    public Map<String, Object> getStoreCodeList(Long custAccId, CodeInStoreListSearchVo searchVo) {
        PageUtil.setPageLimit(searchVo);
        List<ZjCode> codeList = codeService.getStoreCodeList(custAccId, searchVo);
        List<Long> goodsIds = codeList.stream().map(ZjCode::getGoodsId).distinct().toList();
        List<Long> goodsSpecIds = codeList.stream().map(ZjCode::getGoodsSpecId).distinct().toList();
        List<ViewGoods> goodsList = viewGoodsService.getByGoodsIdsAndGoodsSpecIds(goodsIds, goodsSpecIds);
        List<CodeInStoreListVo> voList = codeList.stream().map(code -> {
            return getStoreCodeData(goodsList, code);
        }).toList();
        return PageUtil.pageList(searchVo.getPage(), searchVo.getLimit(), codeService.getStoreCodeListCount(custAccId, searchVo), voList);
    }

    private CodeInStoreListVo getStoreCodeData(List<ViewGoods> goodsList, ZjCode code) {
        CodeInStoreListVo vo = new CodeInStoreListVo();
        BeanUtil.copyProperties(code, vo);
        vo.setCode(code.getSecurityCode());
        goodsList.stream().filter(f -> Objects.equals(f.getGoodsType(), code.getType()) && Objects.equals(f.getId(), code.getGoodsId()) && Objects.equals(f.getSpecId(), code.getGoodsSpecId())).findFirst().ifPresent(pro -> {
            vo.setGoodsBrand(pro.getBrand());
            vo.setGoodsModel(pro.getModel());
            vo.setGoodsName(pro.getName());
            vo.setGoodsUnit(pro.getUnit());
            vo.setGoodsSpecName(pro.getSpecName());
        });
        return vo;
    }


}



